

#include "zeppreactor.h"

typedef struct connect_entity {
    char url[128];
    char methon[32];
    char version[32];
} connect_entity;


// 主状态机状态
typedef enum CHECK_STATE {
    CHECK_STATE_REQUESTLINE = 0,    // 正在分析请求行
    CHECK_STATE_HEADER,             // 正在分析头部字段
    CHECK_STATE_CONTENT             // 正在分析内容
} CHECK_STATE;

// 从状态机状态
typedef enum LINE_STATUS {
    LINE_OK = 0,        // 读取到一个完整的行
    LINE_BAD,           // 行出错
    LINE_OPEN           // 行数据尚不完整
} LINE_STATUS;

// 服务器处理HTTP请求的结果：
typedef enum HTTP_CODE {
    NO_REQUEST,         // 表示请求不完整,需要继续读取客户数据
    GET_REQUEST,        // 表示获得了一个完整的客户请求
    BAD_REQUEST,        // 表示客户请求有语法错误
    FORBIDDEN_REQUEST,  // 表示客户对资源没有足够的访问权限
    INTERNAL_ERROR,     // 表示服务器内部错误
    CLOSED_CONNECTION   // 表示客户端已经关闭连接
} HTTP_CODE;

LINE_STATUS parse_line(char *buffer, int *checked_index, int *read_index);
HTTP_CODE parse_reauestline(connect_entity *conn, char *temp, CHECK_STATE *checkstate);
HTTP_CODE parse_headers(char *temp);
HTTP_CODE parse_content(connect_entity *conn, char *buffer, int *checked_index, CHECK_STATE *checkstate, int *read_index, int *start_line);

LINE_STATUS parse_line(char *buffer, int *checked_index, int *read_index) {
    char temp;
    for (; *checked_index < *read_index; (*checked_index) ++) {
        temp = buffer[(*checked_index)];
        if (temp == '\r') {
            if ((*checked_index) + 1 == (*read_index)) {
                return LINE_OPEN;
            } else if (buffer[(*checked_index) + 1] == '\n') {
                buffer[(*checked_index) ++] = '\0';
                buffer[(*checked_index) ++] = '\0';
                return LINE_OK;
            }
            return LINE_BAD;
        } else if (temp == '\n') {
            if (((*checked_index) > 1) && buffer[(*checked_index) - 1] == '\r') {
                buffer[(*checked_index) - 1] = '\0';
                buffer[(*checked_index) ++] = '\0';
                return LINE_OK;
            }
            return LINE_BAD;
        }
    }
    return LINE_OPEN;
}

HTTP_CODE parse_reauestline(connect_entity *conn, char *temp, CHECK_STATE *checkstate) {
    char *methon = temp;
    if (strncasecmp(methon, "GET", 3) != 0) {
        return BAD_REQUEST;
    }

    char *url = strpbrk(temp, " \t");
    if (!url) {
        return BAD_REQUEST;
    }
    *(url ++) = '\0';
    url += strspn(temp, " \t");
    if (strncasecmp(url, "http://", 7) == 0) {
        url += 7;
        url = strchr(url, '/');
    }
    if (!url || url[0] != '/') {
        return BAD_REQUEST;
    }


    char *version = strpbrk(url, " \t");
    if (!version) {
        return BAD_REQUEST;
    }
    *(version ++) = '\0';
    version += strspn(url, " \t");
    if (strncasecmp(version, "HTTP/1.1", 8) != 0) {
        return BAD_REQUEST;
    }

    strcpy(conn->methon, methon);
    strcpy(conn->url, url);
    strcpy(conn->version, version);

    *checkstate = CHECK_STATE_HEADER;
    return NO_REQUEST;
}

HTTP_CODE parse_headers(char *temp) {
    if (temp[0] == '\0') {
        return GET_REQUEST;
    } else if (strncasecmp(temp, "Host:", 5) == 0) {
        temp += 5;
        temp += strspn(temp, " \t");
        printf("The request host is: %s\n", temp);
    } else {
        printf("I can not handle this header\n");
    }
    return NO_REQUEST;
}

HTTP_CODE parse_content(connect_entity *conn, char *buffer, int *checked_index, CHECK_STATE *checkstate, int *read_index, int *start_line) {
    LINE_STATUS linestatus = LINE_OK;
    HTTP_CODE retcode = NO_REQUEST;

    while((linestatus = parse_line(buffer, checked_index, read_index)) == LINE_OK) {
        char *temp = buffer + *start_line;
        *start_line = *checked_index;

        switch (*checkstate) {
            case CHECK_STATE_REQUESTLINE:
                retcode = parse_reauestline(conn, temp, checkstate);
                if (retcode == BAD_REQUEST)
                    return BAD_REQUEST;
                break;
            case CHECK_STATE_HEADER:
                retcode = parse_headers(temp);
                if (retcode == BAD_REQUEST)
                    return BAD_REQUEST;
                else if (retcode == GET_REQUEST)
                    return GET_REQUEST;
                break;
            default:
                return INTERNAL_ERROR;
        }
    }

    if (linestatus == LINE_OPEN) {
        return NO_REQUEST;
    } else {
        return BAD_REQUEST;
    }
}


int fsm_parse_http_request(struct zeppevent *ev) {
    
    return 0;
}

